package com.newy.service.sys;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Cache;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.stat.SecondLevelCacheStatistics;
import org.hibernate.stat.Statistics;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.newy.core.BaseService;
import com.newy.core.util.ReflectionUtils;
import com.newy.core.web.AppContext;

/**
 * 工具服务类，提供一些快捷方法，这些方法不与业务相关
 * @author linzongxue
 * @create_date 2011-12-14
 */
@Service
@Transactional
public class UtilService extends BaseService{
	@Transactional(readOnly=true)
	public Object getEntity(Class<?> clazz, Long id){
		return this.getSession().get(clazz, id);
	}
	/**
	 * 获取某个具有树形结构的实体的某个属性值的路径，从根节点开始，以“/”为分隔符
	 * @param id 指定的实体ID
	 * @param attrName 要获取其路径的属性名称，默认为"id"
	 * @param className 实体类全名
	 * @param parentName 指定父节点的属性名，默认为parentId
	 * @return 指定属性的路径，从根节点开始，以“/”为分隔符
	 */
	@SuppressWarnings("rawtypes")
	@Transactional(readOnly=true)
	public String getEntityAttrPath(Long id, String attrName, String parentName, String className){
		if (id == null)
			return null;
		if (attrName == null) attrName = "id";
		if (parentName == null) parentName = "parentId";
		try {
			List<Object> ids = new ArrayList<Object>();
			Class clazz = Class.forName(className);
			Object entity = getSession().get(clazz, id);
			while(true){
				if (entity == null) break;
				ids.add(0, ReflectionUtils.invokeGetterMethod(entity, attrName));
				Object parentId = ReflectionUtils.invokeGetterMethod(entity, parentName);
				if (parentId == null) break;
				entity = getSession().get(clazz, (Long)parentId);
			}
			return StringUtils.join(ids, "/");
		} catch (ClassNotFoundException e) {
			throw new RuntimeException("找不到实体类：" + className);
		}
	}
	
	/**
	 * 获取Hibernate二级缓存中所有实体的相关信息，包括name、countInMemory、countOnDisk和sizeInMemory
	 * @return Map列表 
	 */
	@Transactional(readOnly=true)
	public List<Map<String, Object>> getAllEntitiesCacheInfo(){
		List<Map<String, Object>> allCache = new ArrayList<Map<String, Object>>();
		Statistics stats = getSessionFactory().getStatistics();
		String[] allEntityNames = stats.getSecondLevelCacheRegionNames();
		Arrays.sort(allEntityNames);
		for (String name : allEntityNames){
			Map<String, Object> item = new HashMap<String, Object>();
			SecondLevelCacheStatistics  cacheStats = stats.getSecondLevelCacheStatistics(name);
			item.put("name", name);
			item.put("countInMemory", cacheStats.getElementCountInMemory());
			item.put("countOnDisk", cacheStats.getElementCountOnDisk());
			item.put("sizeInMemory", cacheStats.getSizeInMemory());
			allCache.add(item);
		}
		return allCache;
	}
	
	/**
	 * 删除二级缓存中指定实体的缓存
	 */
	public boolean removeEntityFromCache(String entityName, Long id){
		Cache cache = getSessionFactory().getCache();
		if (cache.containsEntity(entityName, id)){
			cache.evictEntity(entityName, id);
			return true;
		}
		return false;
	}
	
	/**
	 * 删除二级缓存中指定类型的所有实体的缓存
	 */
	public void removeEntityRegionFromCache(String entityName){
		getSessionFactory().getCache().evictEntityRegion(entityName);
	}
	
	/**
	 * 删除二级缓存中所有实体的缓存
	 */
	public void removeAllEntitiesFromCache(){
		getSessionFactory().getCache().evictEntityRegions();
	}
	
	private Session getSession(){
		return getSessionFactory().getCurrentSession();
	}
	
	private SessionFactory getSessionFactory(){
		return AppContext.getBean(SessionFactory.class);
	}
}
